//
//  WmcRecognitionResultVM.swift
//  YPWatermarkCamera
//
//  Created by 周诗松 on 2022/10/19.
//

import UIKit

class WmcRecognitionResultVM: WmcBaseVM {
    // Internal

    /// 水印
    var _model: WmcWatermarkDetailModel?
    /// 图片
    var image: UIImage?
    /// 上传图片的resourceId
    var resoureId: String?
    /// 识别结果
    var dataSource: [WmcMediaRecognitionModel] = []
    /// 识别物体的半径
    var radius: Double = 0.0
    /// 是否修改过
    var isCorrected: Bool = false

    var model: WmcWatermarkDetailModel? {
        get {
            return _model
        }
        set {
            _model = updateModel(newValue)
        }
    }

    func fetchRecognitionInfo(success: @escaping ([WmcMediaRecognitionModel]) -> Void, failure: @escaping (Error) -> Void) {
        guard let imageData = image?.jpegData(compressionQuality: 0.95) else { return }
        var params: WmcUploadFileModel = .init()
        params.entryId = 555619
        params.type = 0
        params.format = "jpeg"
        params.wmId = model?.wmId
        params.wmcInfo = model?.toJSON()

        WmcUploadManager.uploadFile(data: imageData, params: params, appId: "101", progress: nil) { [weak self] value in
            guard let weakSelf = self, let model = weakSelf.model else { return }
            weakSelf.resoureId = value.resourceId

            var type: WmcMediaRecognitionAPI.RecognitionType?

            switch model.wmId {
            case 80,
                 107,
                 91:
                type = .rebar
            case 81,
                 106,
                 92:
                type = .pipe
            default: break
            }

            guard let type = type else { return }

            WmcMediaRecognitionAPI.recognizeQuantity(type: type, resourceId: value.resourceId, imgUrl: value.url).subscribe(onNext: { [weak self] list in
                guard let weakSelf = self else { return }
                let result = weakSelf.transformData(list: list)
                weakSelf.dataSource = result
                weakSelf.updateCount(result.count)
                weakSelf.submitWatermarkInfo()
                success(result)
            }, onError: { error in
                failure(error)
            }).disposed(by: weakSelf.rx.disposeBag)
        } failure: { error in
            failure(error)
        }
    }

    func submitWatermarkInfo() {
        let result = convertToWatermarkInfoJson()
        WmcPhotoAPI.submitWatermarkInfo(watermarkType: result.type, type: 1, watermarkInfo: result.watermarkInfo, entry: 555619)
    }

    func submitRecognitionResult(image: UIImage?, success: ((YPNetworkResponse) -> Void)? = nil, failure: ((Error) -> Void)? = nil) {
        guard let imageData = image?.jpegData(compressionQuality: 0.5), let resoureId = self.resoureId else { return }
        var params: WmcUploadFileModel = .init()
        params.entryId = 555620
        params.type = 0
        params.format = "png"
        params.wmId = model?.wmId
        params.wmcInfo = model?.toJSON()

        WmcUploadManager.uploadFile(data: imageData, params: params, appId: "101", progress: nil) { [weak self] value in
            guard let weakSelf = self else { return }

            WmcMediaRecognitionAPI.submitRecognitionData(resourceId: resoureId, newResourceId: value.resourceId, newUrl: value.url, isCorrected: weakSelf.isCorrected).subscribe(onNext: { resp in
                success?(resp)
            }, onError: { error in
                failure?(error)
            }).disposed(by: weakSelf.rx.disposeBag)
        } failure: { error in
            failure?(error)
        }
    }

    func queryUserTip() -> Bool {
        if let isShowed: Bool = WmcUserdefault.object(forKey: .Alert.Recognition.newUserTip) {
            return isShowed
        } else {
            return false
        }
    }

    func updateCount(_ count: Int) {
        guard let model = model else { return }
        for optionModel in model.fields {
            if optionModel.fieldType == .results {
                optionModel.content = "\(count)"
                break
            }
        }
    }

    func saveImage(_ watermarkImg: UIImage?) {
        let result = convertToWatermarkInfoJson()

        if let image = image, WmcCameraSettingVM.checkUseCell(type: .saveNoneWatermarkImage), WmcPreferenceSettingsManager.shared.cameraSetting.saveNoneWatermarkImage {
            WmcLocalMediaAlbumDBManager.insertImage(.init(uiImage: image), watermarkJson: result.watermarkInfo)
        }

        if let watermarkImg = watermarkImg {
            WmcLocalMediaAlbumDBManager.insertImage(.init(uiImage: watermarkImg), watermarkJson: result.watermarkInfo)
        }
    }

    // Private

    private func convertToWatermarkInfoJson() -> (type: String, watermarkInfo: String) {
        var watermarkInfoDic: [String: Any] = model?.toJSON() ?? [:]
        if let date = WmcDateManager.shared.networkDate.value {
            let timeDic: [String: Any] = ["time": date.timeIntervalSince1970, "isNetTime": true]
            watermarkInfoDic["time"] = timeDic
        } else {
            let timeDic: [String: Any] = ["time": Date().timeIntervalSince1970, "isNetTime": false]
            watermarkInfoDic["time"] = timeDic
        }

        let watermarkType = model?.wmId.yp.string ?? ""

        var json = ""

        if let data = try? JSONSerialization.data(withJSONObject: watermarkInfoDic, options: []) {
            json = String(data: data, encoding: String.Encoding.utf8) ?? ""
        }

        return (type: watermarkType, watermarkInfo: json)
    }

    private func transformData(list: [WmcMediaRecognitionModel]) -> [WmcMediaRecognitionModel] {
        var minValue: Double = .greatestFiniteMagnitude
        list.forEach { model in
            if minValue > model.width {
                minValue = model.width
            }
            if minValue > model.height {
                minValue = model.height
            }
        }
        let radius = minValue / 2.0
        var result: [WmcMediaRecognitionModel] = []
        var idx: Int = 0
        list.forEach { model in
            let temp = model
            temp.radius = radius
            temp.index = idx
            result.append(temp)
            idx += 1
        }
        self.radius = radius
        return result
    }

    private func updateModel(_ model: WmcWatermarkDetailModel?) -> WmcWatermarkDetailModel? {
        guard let model = model else { return nil }

        if let json: String = WmcUserdefault.object(forKey: .Data.Recognition.configsCache) {
            let cacheArray = jsonConvertToArray(json)

            let idx = cacheArray.firstIndex { item in
                return item.wmId == model.wmId
            }

            if let idx = idx {
                let cacheModel = cacheArray[idx]

                var fields: [WmcWatermarkOptionModel] = []

                model.fields.forEach { optionModel in
                    let optionIdx = cacheModel.fields.firstIndex { optionCacheItem in
                        return optionCacheItem.fieldId == optionModel.fieldId
                    }

                    if let optionIdx = optionIdx {
                        let optionCacheModel = cacheModel.fields[optionIdx]
                        optionModel.content = optionCacheModel.content
                        optionModel.isOpen = optionCacheModel.isOpen
                    }

                    fields.append(optionModel)
                }

                model.fields = fields
            }
        }

        return model
    }

    private func jsonConvertToArray(_ json: String) -> [WmcWatermarkDetailModel] {
        if json == "" || json.count == 0 {
            return []
        }
        var result: [WmcWatermarkDetailModel] = []
        if let data = json.data(using: String.Encoding.utf8), let list = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions()) as? [Any] {
            for item in list {
                if let dict = item as? [String: Any], let model = WmcWatermarkDetailModel.deserialize(from: dict) {
                    result.append(model)
                }
            }
        }
        return result
    }
}
